Sinus rom
Let’s imagine that you want to generate a sine wave and also have a filtered version of it (which is completely useless in practical, but let’s do it as an example).
Parameters name |
Type |
Description |
---|---|---|
resolutionWidth |
Int |
Number of bits used to represent numbers |
sampleCount |
Int |
Number of samples in a sine period |
IO name |
Direction |
Type |
Description |
---|---|---|---|
sin |
out |
SInt(resolutionWidth bits) |
Output which plays the sine wave |
sinFiltered |
out |
SInt(resolutionWidth bits) |
Output which plays the filtered version of the sine |
So let’s define the Component
:
case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
val io = new Bundle {
val sin = out SInt(resolutionWidth bits)
val sinFiltered = out SInt(resolutionWidth bits)
}
...
To play the sine wave on the sin
output, you can define a ROM which contain all samples of a sine period (it could be just a quarter, but let’s do things the most simple way).
Then you can read that ROM with an phase counter and this will generate your sine wave.
// Calculate values for the lookup table
def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
}
val rom = Mem(SInt(resolutionWidth bits),initialContent = sinTable)
val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
phase := phase + 1
io.sin := rom.readSync(phase)
Then to generate sinFiltered
, you can for example use a first order low pass filter implementation:
io.sinFiltered := RegNext(io.sinFiltered - (io.sinFiltered >> 5) + (io.sin >> 5)) init 0
Here is the complete code:
case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
val io = new Bundle {
val sin = out SInt(resolutionWidth bits)
val sinFiltered = out SInt(resolutionWidth bits)
}
// Calculate values for the lookup table
def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
}
val rom = Mem(SInt(resolutionWidth bits),initialContent = sinTable)
val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
phase := phase + 1
io.sin := rom.readSync(phase)
io.sinFiltered := RegNext(io.sinFiltered - (io.sinFiltered >> 5) + (io.sin >> 5)) init 0
}